package net.kazed.nextaction.database.serialize;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

import net.kazed.nextaction.database.Task;
import net.kazed.nextaction.database.TaskStatus;

import org.xml.sax.Attributes;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.net.Uri;

public class TaskHandler extends AbstractElementHandler implements ElementHandlerContext<RestoreTask> {

    private ContentResolver contentResolver;
    private RestoreTask currentTask;
    private Map<Integer, Integer> contextIdTranslation;
    private Map<Integer, Integer> taskIdTranslation;

    public TaskHandler(ContentResolver contentResolver, Map<Integer, Integer> contextIdTranslation) {
        super();
        this.contentResolver = contentResolver;
        this.contextIdTranslation = contextIdTranslation;
        this.taskIdTranslation = new HashMap<Integer, Integer>();
        
        addElementHandler(RestoreTask.ID, new TaskHandler.TaskIdHandler(this));
        addElementHandler(RestoreTask.DESCRIPTION, new TaskHandler.TaskDescriptionHandler(this));
        addElementHandler(RestoreTask.PARENT_TASK_ID, new TaskHandler.TaskParentTaskIdHandler(this));
        addElementHandler(RestoreTask.DETAILS, new TaskHandler.TaskDetailsHandler(this));
        addElementHandler(RestoreTask.CONTEXT_ID, new TaskHandler.TaskContextIdHandler(this));
        addElementHandler(RestoreTask.COMPLETE, new TaskHandler.TaskCompleteHandler(this));
        addElementHandler(RestoreTask.TYPE, new TaskHandler.TaskTypeHandler(this));
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        addElementHandler(RestoreTask.CREATED, new TaskHandler.CreatedDateHandler(this, dateFormat));
        addElementHandler(RestoreTask.MODIFY_DATE, new TaskHandler.ModifiedDateHandler(this, dateFormat));
        addElementHandler(RestoreTask.START_DATE, new TaskHandler.StartDateHandler(this, dateFormat));
        addElementHandler(RestoreTask.DUE_DATE, new TaskHandler.DueDateHandler(this, dateFormat));
    }

    public RestoreTask getCurrentTask() {
        return currentTask;
    }

    @Override
    public void startElement(String name, Attributes attributes,
            ParserState state) {
        currentTask = new RestoreTask();
    }

    @Override
    public void endElement(String name, ParserState state) {
        Integer contextId = contextIdTranslation.get(currentTask.contextId);
        if (contextId == null) {
            contextId = currentTask.contextId;
        }

        if (currentTask.parentTaskId != null) {
            if (taskIdTranslation.containsKey(currentTask.parentTaskId)) {
                currentTask.parentTaskId = taskIdTranslation.get(currentTask.parentTaskId);
            } else {
                currentTask.parentTaskId = null;
            }
        }

        Task task = new Task(currentTask.id, currentTask.description, currentTask.details, contextId,
                currentTask.parentTaskId, currentTask.created, currentTask.modified, currentTask.startDate,
                currentTask.dueDate, currentTask.order, currentTask.completed, currentTask.type);
        ContentValues values = new ContentValues();
        task.toValues(values);
        Uri itemUri = ContentUris.withAppendedId(Task.CONTENT_URI, task.getId());
        int count = contentResolver.update(itemUri, values, null, null);
        if (count == 0) {
            Uri newTaskUri = contentResolver.insert(Task.CONTENT_URI, values);
            String idSegment = newTaskUri.getLastPathSegment();
            Integer newTaskId = Integer.valueOf(idSegment);
            taskIdTranslation.put(currentTask.id, newTaskId);
        } else {
            contentResolver.update(itemUri, values, null, null);
            taskIdTranslation.put(currentTask.id, currentTask.id);
        }
        currentTask = null;
    }
    
    public RestoreTask getContextData() {
        return currentTask;
    }

    public static class TaskIdHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskIdHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().id = Integer.valueOf(text);
        }
    }
    
    public static class TaskDescriptionHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskDescriptionHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().description = text;
        }
        @Override
        public boolean isValueEncoded() {
            return true;
        }
    }
    
    public static class TaskDetailsHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskDetailsHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().details = text;
        }
        @Override
        public boolean isValueEncoded() {
            return true;
        }
    }
    
    public static class TaskParentTaskIdHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskParentTaskIdHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().parentTaskId = Integer.valueOf(text);
        }
    }

    public static class TaskContextIdHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskContextIdHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().contextId = Integer.valueOf(text);
        }
    }

    public static class TaskCompleteHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskCompleteHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().completed = Boolean.parseBoolean(text);
        }
    }

    public static class TaskTypeHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        public TaskTypeHandler(ElementHandlerContext<RestoreTask> handlerContext) {
            super(handlerContext);
        }
        @Override
        public void characters(String text, ParserState state) {
            getContextData().type = TaskStatus.getEnum(Integer.valueOf(text));
        }
    }

    public static class CreatedDateHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        private DateFormat dateFormat;
        public CreatedDateHandler(ElementHandlerContext<RestoreTask> handlerContext, DateFormat dateFormat) {
            super(handlerContext);
            this.dateFormat = dateFormat;
        }
        @Override
        public void characters(String text, ParserState state) {
            try {
                getContextData().created = dateFormat.parse(text);
            } catch (ParseException e) {
                getContextData().created = null;
            }
        }
    }

    public static class ModifiedDateHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        private DateFormat dateFormat;
        public ModifiedDateHandler(ElementHandlerContext<RestoreTask> handlerContext, DateFormat dateFormat) {
            super(handlerContext);
            this.dateFormat = dateFormat;
        }
        @Override
        public void characters(String text, ParserState state) {
            try {
                getContextData().modified = dateFormat.parse(text);
            } catch (ParseException e) {
                getContextData().modified = null;
            }
        }
    }

    public static class StartDateHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        private DateFormat dateFormat;
        public StartDateHandler(ElementHandlerContext<RestoreTask> handlerContext, DateFormat dateFormat) {
            super(handlerContext);
            this.dateFormat = dateFormat;
        }
        @Override
        public void characters(String text, ParserState state) {
            try {
                getContextData().startDate = dateFormat.parse(text);
            } catch (ParseException e) {
                getContextData().startDate = null;
            }
        }
    }

    public static class DueDateHandler extends AbstractElementHandlerWithContext<RestoreTask> {
        private DateFormat dateFormat;
        public DueDateHandler(ElementHandlerContext<RestoreTask> handlerContext, DateFormat dateFormat) {
            super(handlerContext);
            this.dateFormat = dateFormat;
        }
        @Override
        public void characters(String text, ParserState state) {
            try {
                getContextData().dueDate = dateFormat.parse(text);
            } catch (ParseException e) {
                getContextData().dueDate = null;
            }
        }
    }

}
